<?php 
namespace app\admin\controller;

use cmf\controller\AdminBaseController;
use think\Db;
use think\Validate;
use app\admin\model\ContractModel;
use app\admin\model\AccessModel;
use app\admin\model\AdminMenuModel;
use app\api\controller\ApiAccessEncodeController;

/**
* 公司数据备份管理
*/
class CompanyBackupController extends AdminBaseController
{
    
    private $pageNum = 20;
    
    // source path
    const backupSourcePath = "/api/backup/backFile";
    // db  path
    const backupDbPath = "/api/backup/backSql";
    
    //delete path
    const backupDeletePath = "/api/backup/deleteFile";
    
    //backup path
    const backupPath = '/api/backup/export_file';
    
    
    protected $apiaccessObj = null;
    
    
    
    private $statusStr = [ '创建备份' ,  '打包失败' ,'已打包待下载' , '下载失败' , '下载成功' ];
    private $statusColor = [ 'blue' , 'red' , 'orange' , 'red' , 'green' ];
    
    public function  _initialize()
    {
        $this->apiaccessObj = new ApiAccessEncodeController();
    }

    /**
     * 数据备份首页
     */
    public function index()
    {
        //获取公司首页  
        $companyList = Db::name( 'company' )->where('status' , '<>' , 8 )->paginate( $this->pageNum );
        
        foreach( $companyList as $key => $value )
        {
            $value ['addr_source'] = "";
            $value ['addr_db'] = "";
            $companyList [ $key ] = $value;
            if( !empty( $value [ 'commicate_addr' ] )  ){
                $value ['addr_source'] = $value [ 'commicate_addr' ] . self::backupSourcePath ;
                $value ['addr_db'] = $value [ 'commicate_addr' ] . self::backupDbPath;
            }
            
            $source = Db::name( 'company_backup_records' )->where( 'company_id' , $value['id'] )->where('backup_type' , 2)->order('add_time desc')->find();
            $value ['source_status_color'] =  empty($source [  'status' ] ) ? 'red' :  $this->statusColor[ $source ['status'] ]; 
            $value [ 'bak_source_stus' ] =  empty($source [  'status' ] ) ? '未备份' : $this->statusStr[ $source [ 'status' ] ];
            $value [ 'bak_source_time' ] =  empty($source [  'bak_time' ] ) ? '' : date( 'Y/m/d H:i:s'  , $source [ 'bak_time' ] );
            
            $database = Db::name( 'company_backup_records' )->where( 'company_id' , $value['id'] )->where('backup_type' , 1)->order('add_time desc')->find();
            $value ['database_status_color'] =  empty($database [  'status' ] ) ? 'red' :$this->statusColor[$database ['status']];
            $value [ 'bak_db_stus' ] =  empty($database [  'status' ] ) ? '未备份' :   $this->statusStr[ $database [ 'status' ] ];
            $value [ 'bak_db_time' ] = empty($database [  'bak_time' ] ) ? '' : date( 'Y/m/d H:i:s'  , $database [ 'bak_time' ] );
            
            $companyList [$key] = $value; 
        
        }
		$ipInfo = Db::name('company_backup_records')->where(['status'=>8,'backup_type' => 8,'company_id'=>8] )-> find();
		$ipInfo['current_ip'] = $this->getIp();
		$this->assign( "ipInfo" , $ipInfo );
        //$this->assign( 'statusColor' , $this->statusColor );
        $this->assign( 'companyList' , $companyList );
        return $this->fetch( 'company/backup/backup_index' );
    }
    private function getIp()
	{
		if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
			$ip = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
			$ip = trim(current($ip));
		}else{
			$ip = $_SERVER['REMOTE_ADDR'];
		}
		
		return $ip;
	}
    /** 
    *编辑地址页面
    */
    public function commicateAddr()
    {
        $param = $this->request->param();
        $this->assign( 'addr_api' , $param[ 'addr_api' ]);
        return $this->fetch( 'company/backup/commicate_addr' );
    }

    /**
     * 编辑地址
     * 公司表增加 commicate_addr 字段用于保存请求目标备份系统操作地址
     */
    public function editeCommicateAddr()
    {
        
        if( !$this->request->isAjax() )  return zy_json_echo( false , '请求类型错误!');
        $param = $this->request->param();
        $company_id = $param [ 'id' ];
        $res = Db::name( 'company' )->where( 'id' , $company_id )->update( [ 'commicate_addr' => $param['addr_api'] ] );
        if( !$res ){
            return zy_json_echo( false, '地址更新失败,请稍后再试!' );
        }
        return zy_json_echo( true , '地址更新成功!' );
    }

    /**
     * 备份记录
     */
    public function backupRecords()
    {
        if( !$this->request->isPost() ) return zy_json_echo(false , '请求类型错误!');
        $param = $this->request->param();
        
		dump($param); exit;
        $operator_id = cmf_get_current_admin_id();
        $operator = Db::name( 'user' )->where( 'id' , $operator_id )->value( 'user_login' );

        $insert = [
            'company_id' => $param [ 'id' ],
            'add_time'  => time(),
            'operator_id'   => $operator_id,
            'operator'  => $operator,
            'remarks'   => $param [ 'remarks' ] ,
            'status' => 0 //未备份
        ];
        $res = Db::name( 'company_backup_records' )->insertGetId( $insert );
        if( !$res ){
            return zy_json_echo( false , '备份记录保存失败,请稍后再试!' );
        }
        return zy_json_echo( true , '备份记录保存成功!' );
    }

    /**
     * 查看备份详情页
     */
    public function recordParticular( $id )
    {
        $param = $this->request->param();
        $bak_type = 0 ;
        if( isset ( $param [ 'bak_type' ] ) ) $bak_type = $param[ 'bak_type' ];
        
        $list = Db::name( 'company_backup_records' )->where('status' , '<>' , 8 )->order('add_time desc');
        if( $bak_type !=0 ){
            $list = $list -> where( 'backup_type'  , $bak_type );
        }
        $list = $list->paginate($this->pageNum);
        foreach ( $list as $key => $value ){
            $value [ 'status_str' ] =  empty( $value [ 'status' ] ) ? '未备份': $this->statusStr[ $value [ 'status' ] ];
            $value [ 'status_color' ] = empty( $value [ 'status' ] ) ? 'red' : $this->statusColor[ $value [ 'status' ]  ] ;
            $list [ $key ] = $value; 
        }
        $this->assign( 'bak_type' , $bak_type );
        $this->assign( 'list' , $list );
        $this->assign( 'id' , $id );
        //dump($list);exit;
        return $this->fetch( 'company/backup/record_particular' );
    }
    
    //delete backup record
    public function deleteRecord($id){
        $res = Db::name( 'company_backup_records' )->where( 'id' , $id )->delete();
        if(!$res ){
            return zy_json_echo(false , '删除失败！' );
        }
        return zy_json_echo(true , '删除成功！');
    }
    
    
    //open subsystem backup page
    public function backupList( $id , $addr_api )
    {
        $this->assign( 'id' , $id );
        $this->assign( 'addr_api', base64_encode(urlencode($addr_api)) );
        return $this->fetch( 'company/backup/back_file' );
    }
    
    /**
     * 获取文件列表
     */
    public function dirList( $result )
    {
        $tree       = new Tree();
        $tree->icon = ['&nbsp;&nbsp;&nbsp;│ ', '&nbsp;&nbsp;&nbsp;├─ ', '&nbsp;&nbsp;&nbsp;└─ '];
        $tree->nbsp = '&nbsp;&nbsp;&nbsp;';
        foreach ($result as $key => $value) {
            $result[$key]['parent_id_node'] = ($value['parent_id']) ? ' class="child-of-node-' . $value['parent_id'] . '"' : '';
            $result[$key]['style']          = empty($value['parent_id']) ? '' : 'display:none;';
            $result[$key]['checkbox'] = $value['id'] == 1 ? "" : '<input type="checkbox" value='.$value['path'].' />';
            $result[$key]['icon'] = !empty($value['type']) ? '<span class="glyphicon glyphicon-folder-close"></span>' : '<span class="glyphicon glyphicon-menu-hamburger"></span>';
        }

        $tree->init($result);
        $str      = "<tr id='node-\$id'  \$parent_id_node style='\$style ; cursor:pointer;'>
        <td style='padding-left:20px;'><label>\$checkbox &nbsp;&nbsp; \$icon \$name</label></td>
        <td>\$path </td>
        </tr>";
        $list = $tree->getTree(0, $str);
        $this->assign( 'list' , $list );
        return $this->fetch('dir_list');
    }
    
    
    //backup db
    public function backupDb( $id )
    {   
        
        $find = Db::name('company')->where( 'id' , $id )->find( );
        $name = $this->createFileNme(1);
        
        $param = [
            'cid' => $find['id'] ,
            'filename' => $name
        ];
        $param = $this->assemblyParam( $param );
        
        $addr = $find['commicate_addr'].self::backupDbPath.'?'.$param;
        $jsonStr = cmf_curl_get( $addr );
        
        $res = json_decode( $jsonStr, true );
        //dump($res);exit;
        if( !isset( $res [ 'code' ] )  || isset( $res [ 'code' ] ) && $res[ 'code' ] != 200  ){
            return zy_json_echo( false , $res [ 'message' ] );
        }
        $data = $res [ 'data' ] ;       
        //create rocord
        
        // `id`=[value-1],`company_id`=[value-2],`operator`=[value-3],`operator_id`=[value-4],`add_time`=[value-5],`status`=[value-6],`bak_time`=[value-7],`remarks`=[value-8] WHERE 1
        $addr = $data [ 'url' ] ;
        $r = $this->createRecord ( $find [ 'id' ] , $addr , $name , 2 , $res['message'] , 1 );
        if( !$r ){
            return zy_json_echo(false , '添加记录失败，请稍候再试！' );
        }
        return zy_json_echo( true, '操作成功！');
        
    }
    
    //create record
    private function  createRecord( $companyId , $addr , $filename ,  $status, $remarks , $backupType=0 )
    {
        $user_id = cmf_get_current_admin_id();
        $insert = [
        
            'company_id' => $companyId,
            'operator' => Db::name( 'user' )->where( 'id' , $user_id )->value( 'user_login' ),
            'filename' => $filename,
            'operator_id' => $user_id,
            'add_time' => time(),
            'addr'  => $addr,
            'status' => $status,
            'remarks' => $remarks,
            'backup_type' => $backupType
        ];
        $res = Db::name( 'company_backup_records' )->insertGetId( $insert );
        return empty( $res )?false:true;
    }
    
    
    // getFileDir
    public function getDir( $addr_api , $dir = "" , $cid )
    { 
        $addr_api = urldecode( base64_decode( $addr_api ) );
        $param = [
            'cid' => $cid,
            'path' => $dir
        ];
        $param = $this->assemblyParam($param);
        $addr_api .= '?'.$param; 
        $list = cmf_curl_get( $addr_api );
        $list = json_decode( $list , true );
        if( !isset( $list [ 'data' ] ) || !isset( $list [ 'code' ] ) || $list [ 'code' ] != 200  ){
            return zy_json_echo(false , '数据获取失败!');
        }
        return zy_json_echo( true ,  '成功！' , $list['data'] );       
    }
        
    //excute backup
    public function excuteBackup()
    {
        if( !$this->request->param()){
            return zy_json_echo( false , 'request  type is error !' );
        }
        $param = $this->request->param();
        
        $backupList = "sdfs5df45sd4f5sdf65sdfsd65f4";
        if( isset( $param [ 'list' ] ) && !empty( $param [ 'list' ] ) ){
            $backupList = $param [ 'list' ];
            foreach( $backupList as $key => $value ){
                $value = str_replace( '\\' , '/' , $value );
                $backupList [ $key ] = $value;
            }
        
        }
        
        $remarks  = $param['remarks']; 
        $id = $param [ 'id' ] ;
        $find = Db::name('company')->where( 'id' , $id )->find( );
        $addr = $find['commicate_addr'].self::backupPath;
        $addr_api  = $find[ 'commicate_addr' ];
        
        $addr_api .= self::backupPath; //.'?list='.$backupList;

        //$res = cmf_curl_get( $addr_api );
        $name = $this->createFileNme();
        $pm = [
            'cid' => $id,
            'list' => $backupList,
            'filename'=> $name
        ];
		
        
        $pm = $this->assemblyParam( $pm , 1 );

        //dump($pm);exit;
        $res = $this->curlPost( $addr_api , $pm );

        $res = json_decode( $res , true );

        $status = 1 ;  
        if( isset( $res [ 'status' ] ) && $res [ 'status' ] == "success" ){
            $status = 2 ; //
        }
        //add backup record
        $url = isset( $res [ 'data' ] [ 'url' ] ) ? $res [ 'data' ] [ 'url' ] : '';
        $filename = isset( $res [ 'data' ] [ 'filename' ] ) ? $res [ 'data' ] [ 'filename' ] : '' ;
        $downloadAddr = '';
        if( !empty($filename) ){
            //$downloadAddr = $url . "?filename=" . $filename;
			$downloadAddr = $url;
        }
        $message = isset( $res [ 'message' ] ) ? $res [ 'message' ] : '';
        $r = $this->createRecord ( $find [ 'id' ] , $downloadAddr , $name  , $status , $remarks.$message , 2 );
        echo 1;
        
    }
    
    //createName
    private function createFileNme( $type  = 0 )
    {
        $str = ( $type == 0 ) ? "code" : "db" ;
        $file_name = cmf_random_string(10).'_'.$str.'_'.date('Ymd').'.zip';
        return $file_name;
    }
    
    //
    private function curlPost( $url , $param = [] )
    {
         /*$curl = curl_init();//设置抓取的url
         curl_setopt($curl, CURLOPT_URL, $url );
         //设置头文件的信息作为数据流输出
        // curl_setopt($curl, CURLOPT_HEADER, 1);
         //设置获取的信息以文件流的形式返回，而不是直接输出
         //curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
         
         //设置post方式提交
         curl_setopt($curl, CURLOPT_POST, 1);
         //设置post数据
         $post_data = http_build_query($param);
         curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data);
         //执行命令
         $data = curl_exec($curl);
         //关闭URL请求
         curl_close($curl);
         //显示获得的数据
        return $data;*/
        
        $ch = curl_init();

        //指定URL
        curl_setopt($ch, CURLOPT_URL, $url);

        // 在尝试连接时等待的秒数

        //设定请求后返回结果
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

        //声明使用POST方式来进行发送
        curl_setopt($ch, CURLOPT_POST, 1);
        $data = http_build_query($param);
        //发送什么数据呢
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);


        //忽略证书
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

        //忽略header头信息
        curl_setopt($ch, CURLOPT_HEADER, 0);

        //设置超时时间
        curl_setopt($ch, CURLOPT_TIMEOUT, 600);

        //发送请求
        $output = curl_exec($ch);

        //关闭curl
        curl_close($ch);

        //返回数据
        return $output;
    }
    
    
    // assembly param 
    private function assemblyParam( $param , $str = 0 )
    {   
		if( $str == 0 ){
			return http_build_query($this->apiaccessObj->signCode( $param ));
		}
        return $this->apiaccessObj->signCode( $param );
    }
    
    
    
    




}